
#ifndef TP_PIPE_H
#define TP_PIPE_H

TP_DECL_BEGIN

struct _TpPipe;
typedef struct _TpPipe TpPipe;

typedef int (*TpPipeRead)(TpPipe* thiz, void* buffer, size_t len);

typedef int (*TpPipeWrite)(TpPipe* thiz, void* data, size_t size);

/* we can use select() to check the returned fd to see whether it's readable/writable. */
typedef int (*TpPipeGetWriteFd)(TpPipe* thiz);
typedef int (*TpPipeGetReadFd)(TpPipe* thiz);

typedef void (*TpPipeDestroy)(TpPipe* thiz);

struct _TpPipe
{
	TpPipeRead read;
	TpPipeWrite write;
	TpPipeGetWriteFd get_write_fd;
	TpPipeGetReadFd get_read_fd;
	TpPipeDestroy destroy;

	char priv[1];
};

static inline int tp_pipe_read(TpPipe* thiz, void* buffer, size_t len)
{
	if(NULL == thiz || NULL == thiz->read || NULL == buffer || 0 == len) return 0;

	return thiz->read(thiz, buffer, len);
}

static inline int tp_pipe_write(TpPipe* thiz, void* data, size_t size)
{
	if(NULL == thiz || NULL == thiz->write || NULL == data || 0 == size) return 0;

	return thiz->write(thiz, data, size);
}

static inline int tp_pipe_get_read_fd(TpPipe* thiz)
{
	if(NULL == thiz || NULL == thiz->get_read_fd) return -1;

	return thiz->get_read_fd(thiz);
}

static inline int tp_pipe_get_write_fd(TpPipe* thiz)
{
	if(NULL == thiz || NULL == thiz->get_write_fd) return -1;

	return thiz->get_write_fd(thiz);
}

static inline void tp_pipe_destroy(TpPipe* thiz)
{
	if(NULL != thiz && NULL != thiz->destroy)
	{
		thiz->destroy(thiz);
	}

	return;
}

TpPipe* tp_pipe_create(void);

TP_DECL_END

#endif /* TP_PIPE_H */